import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import time
from mlxtend.preprocessing import TransactionEncoder
from mlxtend.frequent_patterns import fpgrowth, association_rules
import psutil

# 添加中文字体设置
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']  # 设置微软雅黑字体
plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题

# 定义商品类别映射
category_mapping = {
    '智能手机': '电子产品', '笔记本电脑': '电子产品', '平板电脑': '电子产品',
    '智能手表': '电子产品', '耳机': '电子产品', '音响': '电子产品',
    '相机': '电子产品', '摄像机': '电子产品', '游戏机': '电子产品',
    '上衣': '服装', '裤子': '服装', '裙子': '服装', '内衣': '服装',
    '鞋子': '服装', '帽子': '服装', '手套': '服装', '围巾': '服装',
    '外套': '服装', '零食': '食品', '饮料': '食品', '调味品': '食品',
    '米面': '食品', '水产': '食品', '肉类': '食品', '蛋奶': '食品',
    '水果': '食品', '蔬菜': '食品', '家具': '家居', '床上用品': '家居',
    '厨具': '家居', '卫浴用品': '家居', '文具': '办公', '办公用品': '办公',
    '健身器材': '运动户外', '户外装备': '运动户外', '玩具': '玩具',
    '模型': '玩具', '益智玩具': '玩具', '婴儿用品': '母婴',
    '儿童课外读物': '母婴', '车载电子': '汽车用品', '汽车装饰': '汽车用品'
}


def get_memory_usage():
    """获取当前内存使用情况（GB）"""
    process = psutil.Process()
    return process.memory_info().rss / 1e9

# 记录内存使用
memory_usage = []
times = []

start_time = time.time()
memory_usage.append(get_memory_usage())
times.append(time.time() - start_time)

# -------------------
# 数据预处理
# -------------------
# 读取数据集
print("读取数据中...")
purchase_history = pd.read_csv('D:/DTR/MyWork/2025/DataMining/personalProject/output/items_10G_one.csv')
product = pd.read_csv('D:/DTR/MyWork/2025/DataMining/personalProject/output/product.csv')

memory_usage.append(get_memory_usage())
times.append(time.time() - start_time)
print(f"数据读取完成，内存使用: {memory_usage[-1]:.2f} GB")

# 处理items列（将字符串转换为列表）
print("处理数据中...")
purchase_history['items'] = purchase_history['items'].apply(lambda x: eval(x))

# 合并订单数据与商品类别数据
merged_product = purchase_history.explode('items').merge(product, left_on='items', right_on='id', how='left')

memory_usage.append(get_memory_usage())
times.append(time.time() - start_time)
print(f"数据合并完成，内存使用: {memory_usage[-1]:.2f} GB")

# 将商品类别进行映射
#merged_product['category'] = merged_product['category'].map(category_mapping)

# 转换为事务数据集格式（每个订单对应一个类别列表）
transactions = merged_product.groupby('purchase_date')['category'].apply(list).tolist()

memory_usage.append(get_memory_usage())
times.append(time.time() - start_time)
print(f"事务数据构建完成，内存使用: {memory_usage[-1]:.2f} GB")

# -------------------
# 优化的关联规则挖掘
# -------------------
# 使用稀疏矩阵编码事务数据
print("编码事务数据中...")
te = TransactionEncoder()
te_ary = te.fit(transactions).transform(transactions, sparse=True)  # 使用稀疏矩阵
df_encoded = pd.DataFrame.sparse.from_spmatrix(te_ary, columns=te.columns_)

memory_usage.append(get_memory_usage())
times.append(time.time() - start_time)
print(f"事务数据编码完成，内存使用: {memory_usage[-1]:.2f} GB")

# 使用fpgrowth算法挖掘频繁项集（支持度≥0.02）
print("挖掘频繁项集中...")
frequent_itemsets = fpgrowth(df_encoded, min_support=0.02, use_colnames=True)

memory_usage.append(get_memory_usage())
times.append(time.time() - start_time)
print(f"频繁项集挖掘完成，内存使用: {memory_usage[-1]:.2f} GB")

# 生成关联规则（置信度≥0.5）
print("生成关联规则中...")
rules = association_rules(
    frequent_itemsets, 
    metric="confidence", 
    min_threshold=0.5, 
    num_itemsets=len(df_encoded)
)

memory_usage.append(get_memory_usage())
times.append(time.time() - start_time)
print(f"关联规则生成完成，内存使用: {memory_usage[-1]:.2f} GB")

# 筛选包含电子产品的规则
electronics_rules = rules[
    rules['antecedents'].apply(lambda x: '电子产品' in x) | 
    rules['consequents'].apply(lambda x: '电子产品' in x)
]

# -------------------
# 结果分析与可视化
# -------------------
print("=== 频繁项集分析 ===")
print(f"总频繁项集数量: {len(frequent_itemsets)}")
print("前5大高频单商品项集:")
print(frequent_itemsets[frequent_itemsets['itemsets'].apply(len)==1].sort_values('support', ascending=False).head())

print("\n=== 关联规则分析 ===")
print(f"总关联规则数量: {len(rules)}")
print("高置信度规则示例:")
print(rules.sort_values('confidence', ascending=False).head())
print(rules)

print("\n=== 电子产品关联规则 ===")
if electronics_rules.empty:
    print("未发现满足条件的电子产品关联规则")
else:
    print(electronics_rules.sort_values('confidence', ascending=False))

print(electronics_rules)

# 可视化高频项集分布
plt.figure(figsize=(12, 6))
plt.barh(
    y=frequent_itemsets[frequent_itemsets['itemsets'].apply(len)==1]['itemsets'].apply(lambda x: ', '.join(x)),
    width=frequent_itemsets[frequent_itemsets['itemsets'].apply(len)==1]['support'],
    height=0.5,
    color='skyblue'
)
plt.title("单商品频繁项集支持度分布")
plt.xlabel("支持度")
plt.ylabel("商品类别")
plt.gca().invert_yaxis()  # 按支持度降序显示
plt.tight_layout()
plt.savefig('frequent_itemsets.png')  # 保存图像而非显示，减少内存占用

# 可视化规则置信度与支持度关系
plt.figure(figsize=(10, 6))
plt.scatter(
    x=rules['support'], 
    y=rules['confidence'], 
    alpha=0.6, 
    c='red', 
    edgecolors='black'
)
plt.xlabel("支持度")
plt.ylabel("置信度")
plt.title("关联规则支持度 vs 置信度")
plt.grid(True)
plt.savefig('rules_confidence_support.png')  # 保存图像而非显示

# 可视化内存使用情况
plt.figure(figsize=(10, 6))
plt.plot(times, memory_usage, marker='o', color='blue')
plt.title("内存使用情况")
plt.xlabel("时间（秒）")
plt.ylabel("内存使用（GB）")
plt.grid(True)
plt.savefig('memory_usage.png')

end_time = time.time()
print(f"\n处理完成！")
print(f"- 总耗时: {end_time - start_time:.2f} 秒")
print(f"- 最大内存使用: {max(memory_usage):.2f} GB")


end_time=time.time()
print(f"\n转换完成！")
print(f"- 耗时: {end_time - start_time:.2f} 秒")

